#ifndef MESHES_PARSER_H
#define MESHES_PARSER_H

#include "stdafx.h"
#include<vector>
#include "Maths.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <assert.h>
#include <Windows.h>

#define FLOAR_LENGTH 7
using namespace std;

class ObjectParser
{
public:
	static vector<Triangle<float>*> ParseObjFile(string path, Vec3<float> position )
	{
		vector<Vec3<float>> allVertices;
		vector<Triangle<float>*> allTriangles;
		string line;
		ifstream myfile (path);
		if (myfile.is_open())
		{
			while ( getline (myfile,line))
			{
				vector<string> tokens;
				string currentToken = "";
				char firstChar = ' ';
				if(line[0] != '\0' && !(line[0] == 'v' && line[1] == 'n' ) && line[0] != '#' && line[0] != 'g')
				{
					for(int index = 0; index <= line.size(); index++)
					{
						if(index == 0)
						{
							firstChar = line[index];
						
							if(firstChar == 'v' && line[1] == 'n' || firstChar == '#' || firstChar == 'g')
							{
								tokens.push_back("-");
								break;
							}
					
						}
				
						if( index < line.size() && line[index] != ' ' )
						{
							if(line[index] == '/')
							{
								while(index + 1 != line.size() && line[index + 1] != ' ')
								{
									index ++;
								}
							}
							else if(line[index] != '-')
							{
								string currentString = "";
								int subIndex =index;
								int length = 0;
								while(line[subIndex] != ' ' && subIndex < line.size())
								{
									subIndex ++;
									length++;
								}

								currentToken.append(line,index, length);
								tokens.push_back(currentToken);
								currentToken = "";
								index += length;
							}
				
						}
						else 
						{
							tokens.push_back(currentToken);
							currentToken = "";
						}
					}
				
					//first token is always what is the type mof the object eg V or F
					string typeOfLine = tokens[0];
					if(tokens[0].compare("v") == 0)
					{
						float xCoor =((atof(tokens[1].c_str()) * 2)+position.x);
						float yCoor = ((atof(tokens[2].c_str())* 2) + position.y);
						float zCoor = ((atof(tokens[3].c_str())* 2) + position.z) ;

						/*float xCoor = atof(tokens[1].c_str());
						float yCoor = atof(tokens[2].c_str());
						float zCoor = atof(tokens[3].c_str());*/

						Vec3<float> currentVector(xCoor, yCoor, zCoor);
						
						allVertices.push_back(currentVector);
					}
					else if(tokens[0].compare("f") == 0)
					{
						int a = (int)atoi(tokens[1].c_str());
						int b = (int)atoi(tokens[2].c_str());
						int c = (int)atoi(tokens[3].c_str());

						Vec3<float> coor1 = allVertices[a - 1];
						Vec3<float> coor2 = allVertices[b - 1];
						Vec3<float> coor3 = allVertices[c - 1];

						Triangle<float>  *currentTriangle = new Triangle<float>(coor1, coor2, coor3);
						allTriangles.push_back(currentTriangle);
					} 
				}
				tokens.clear();
				
			}

			myfile.close();
		}
		else cout << "Unable to open file"; 
		return allTriangles;
	}

	static vector<Vec3<float>> GetPoints(string path, Vec3<float> position )
	{
		vector<Vec3<float>> allVertices;
		vector<Triangle<float>*> allTriangles;
		string line;
		ifstream myfile (path);
		if (myfile.is_open())
		{
			while ( getline (myfile,line))
			{
				vector<string> tokens;
				string currentToken = "";
				char firstChar = ' ';
				if(line[0] != '\0' && !(line[0] == 'v' && line[1] == 'n' ) && line[0] != '#' && line[0] != 'g')
				{
					for(int index = 0; index <= line.size(); index++)
					{
						if(index == 0)
						{
							firstChar = line[index];
						
							if(firstChar == 'v' && line[1] == 'n' || firstChar == '#' || firstChar == 'g')
							{
								tokens.push_back("-");
								break;
							}
					
						}
				
						if( index < line.size() && line[index] != ' ' )
						{
							if(line[index] == '/')
							{
								while(index + 1 != line.size() && line[index + 1] != ' ')
								{
									index ++;
								}
							}
							else if(line[index] != '-')
							{
								string currentString = "";
								int subIndex =index;
								int length = 0;
								while(line[subIndex] != ' ' && subIndex < line.size())
								{
									subIndex ++;
									length++;
								}

								currentToken.append(line,index, length);
								tokens.push_back(currentToken);
								currentToken = "";
								index += length;
							}
				
						}
						else 
						{
							tokens.push_back(currentToken);
							currentToken = "";
						}
					}
				
					//first token is always what is the type mof the object eg V or F
					string typeOfLine = tokens[0];
					if(tokens[0].compare("v") == 0)
					{
						float xCoor = atof(tokens[1].c_str())+position.x;
						float yCoor = atof(tokens[2].c_str()) + position.y;
						float zCoor = atof(tokens[3].c_str()) + position.z;

						/*float xCoor = atof(tokens[1].c_str());
						float yCoor = atof(tokens[2].c_str());
						float zCoor = atof(tokens[3].c_str());*/

						Vec3<float> currentVector(xCoor, yCoor, zCoor);

						allVertices.push_back(currentVector);
					}
					else if(tokens[0].compare("f") == 0)
					{
						int a = (int)atoi(tokens[1].c_str());
						int b = (int)atoi(tokens[2].c_str());
						int c = (int)atoi(tokens[3].c_str());

						Vec3<float> coor1 = allVertices[a - 1];
						Vec3<float> coor2 = allVertices[b - 1];
						Vec3<float> coor3 = allVertices[c - 1];

						Triangle<float>  *currentTriangle = new Triangle<float>(coor1, coor2, coor3);
						allTriangles.push_back(currentTriangle);
					} 
				}
				tokens.clear();
				
			}

			myfile.close();
		}
		else cout << "Unable to open file"; 
		return allVertices;
	}


	size_t getFilesize(const char* filename) 
	{
		struct stat st;
		stat(filename, &st);
		return st.st_size;   
	}

//int main(int argc, char** argv) {
//    size_t filesize = getFilesize(argv[1]);
//    //Open file
//    int fd = open(argv[1], O_RDONLY, 0);
//    assert(fd != -1);
//    //Execute mmap
//    void* mmappedData = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd, 0);
//    assert(mmappedData != NULL);
//    //Write the mmapped data to stdout (= FD #1)
//    write(1, mmappedData, filesize);
//    //Cleanup
//    int rc = munmap(mmappedData, filesize);
//    assert(rc == 0);
//    close(fd);
//}

	static vector<Triangle<float> *> FastObjParser(string filePath, Vec3<float> position)
	{

	}
};

#endif 